/**
 * @file adpt_alarm.c
 * @synopsis  
 * @author wen wjcapple@163.com
 * @version 2.0
 * @date 2016-12-29
 */
#include "global.h"
#include "adpt_alarm.h"
#ifdef __cplusplus
extern  "C"{
#endif
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  convert_curv_aglo2alarmmoudle 将曲线从算法模块转换成告警模块所需要
 *						的格式，每次找告警都需要调用
 * @param palgor_curv	算法模块测量所得曲线
 * @param palarm_curv	告警模块需要曲线
 *
 * @returns   0 成功
 */
/* ----------------------------------------------------------------------------*/
int32_t convert_curv_aglo2alarmmoudle(OtdrTestResult_t *palgor_curv,OTDRCurveInfo_t *palarm_curv) 
{
	//采样点
	palarm_curv->testresult.curvepointnum = palgor_curv->tp.DataNum;
	//采样点存放缓冲
	palarm_curv->testresult.curvepoint = palgor_curv->Ai;
	//事件
	convert_event_algor2alarmmodule(palgor_curv->ep, &palarm_curv->testresult,palgor_curv->EventNum);
	//光纤段
	convert_efs_algor2alarmmodule(palgor_curv->fs, &palarm_curv->testresult,palgor_curv->FiberNum);
	//链损耗
	convert_tr_algor2alarmmodule(palgor_curv,&palarm_curv->testresult);
	convert_para_algor2alarmmodule(
			&palgor_curv->tp,
			&palarm_curv->testpara);
		return 0;
}
int32_t convert_stdcfg_host2alarmodule(
		struct _tagFiberSecCfg *pfiber_cfg, 
		struct _tagAlarmModuleAdpt *pAlarmAdpt)
{
	int32_t ret,fiber_count;
	struct _tagHostOtdrPara  host_para;
	struct _tagHostTestResult *phost_tr;
	ret = 0;
	fiber_count = pfiber_cfg->fiber_hdr.count;
	//为光纤段，告警缓存，管理告警缓存分配内存
	malloc_alarmmodule_resource(fiber_count,pAlarmAdpt);
	//给告警模块分配的查找告警的缓冲区需要指明当前通道段数也即告警个数
	pAlarmAdpt->cur_alarm.alarmnum = fiber_count;
	//给告警模块适配的光纤段配置需要指明当前通道段数
	pAlarmAdpt->fiber_sec.fibersegmentnum = fiber_count;
	//告警管理模块需要指明当前通道的光纤段段数
	pAlarmAdpt->alarm_cache.sec_num = fiber_count;
	pAlarmAdpt->sec_num = fiber_count;

	//将光线段从协议转换成告警模块所需的格式
	convert_stdfiber_host2alarmmodule(pfiber_cfg, pAlarmAdpt->fiber_sec.fibersegment,pfiber_cfg->fiber_hdr.count);
	//标准曲线从主机协议格式转换成告警模块所需格式
	pAlarmAdpt->std_curv.testresult.curvepointnum = pfiber_cfg->otdr_hdr.count;
	convert_stddata_host2alarmmodule((int16_t*)pfiber_cfg->otdr_val, 
			pAlarmAdpt->data_buf, 
			pfiber_cfg->otdr_hdr.count);
	//事件点的从主机协议格式转换成告警模块所需要的格式
	pAlarmAdpt->std_curv.testresult.eventnum = pfiber_cfg->event_hdr.count;
	pAlarmAdpt->std_curv.testresult.fibersectionnum = pfiber_cfg->event_hdr.count - 1;
	memset(pAlarmAdpt->std_curv.testresult.sectioninfo, 0, sizeof(FiberSectionByEvent_t)*MAX_EVENT_NUM);
	convert_stdevent_host2alarmmodule((struct _tagOtdrEvent *)pfiber_cfg->event_val,
			pAlarmAdpt->event_buf,
			pfiber_cfg->event_hdr.count);

	memcpy(&host_para.MeasureLength_m, &pfiber_cfg->otdr_param.range, \
			sizeof(struct _tagHostOtdrPara) - 8);
	host_para.slot = pfiber_cfg->otdr_param.slot;
	host_para.pipe = pfiber_cfg->otdr_param.pipe;
	convert_testpara_host2alarmmodule(&host_para, &pAlarmAdpt->std_curv.testpara);

	phost_tr = (struct _tagHostTestResult *)& pfiber_cfg->test_result.range;
	convert_tr_host2alarmmodule(phost_tr, &pAlarmAdpt->std_curv.testresult);
	return ret;

}
//将光线段配置格式从host转换成告警模块格式
int32_t convert_tr_host2alarmmodule(
		const struct _tagHostTestResult *phost_tr,
		OTDRTestResult_t *palarm_tr)
{
		palarm_tr->fiberlen_m = phost_tr->chain;
		palarm_tr->fiberloss_db = phost_tr->loss;
		palarm_tr->fiberattencoef_dbkm = phost_tr->attu;
		return 0;
}
//将配置参数从光线段配置转换到告警模块的格式
int32_t convert_testpara_host2alarmmodule(
		struct _tagHostOtdrPara  *phost_para,
		OTDRTestPara_t *palarm_para)
{
	palarm_para->endthreshold_db = phost_para->EndThreshold;
	palarm_para->gi = phost_para->n;
	palarm_para->lambda_nm = phost_para->Lambda_nm;
	palarm_para->measurelength_m = phost_para->MeasureLength_m;
	palarm_para->nonreflex_db = phost_para->NonRelectThreshold;
	palarm_para->pulsewidth_ns = phost_para->PulseWidth_ns;
	palarm_para->samplerate_hz = phost_para->sample_hz;
	palarm_para->rsvd1 = phost_para->rsv2;
	palarm_para->rsvd2 = phost_para->rsv3;
	palarm_para->testtime_ms = phost_para->MeasureTime_s *1000;
	if(palarm_para->samplerate_hz == 0)
		palarm_para->samplerate_hz = 1;
	return 0;
}
//将光线段配置参数中的标准曲线转换成告警模块所需要的
int32_t convert_stddata_host2alarmmodule(
		int16_t std_data_buf[], 
		float data_buf[], 
		int32_t num)
{
	int32_t ret, i;
	ret = 0;
	for(i = 0; i < num; i++)
	{
		data_buf[i] = std_data_buf[i] / 1000.0;
	}
	return ret;
}
//将光线段配置中的事件的参数转换成告警模块所需要的
int32_t convert_stdevent_host2alarmmodule(
		struct _tagOtdrEvent *pstd_event, 
		OTDREvent_t event_buf[], 
		int32_t num)
{
	int32_t ret, i;
	ret = 0;

	for(i = 0; i < num; i++)
	{
		event_buf[i].startserialnumberpos = pstd_event[i].distance;
		event_buf[i].endserialnumberpos = 0;
		event_buf[i].eventtype = pstd_event[i].type;
		event_buf[i].echoloss_db = pstd_event[i].return_loss;
		event_buf[i].insertloss_db = pstd_event[i].insert_loss;
		event_buf[i].totalloss_db = pstd_event[i].total_loss;
	}
	return ret;

}
//光线段配置转换到告警模块格式
int32_t convert_stdfiber_host2alarmmodule(
		struct _tagFiberSecCfg *pfiber_cfg, 
		FiberSegment_t *fiber_val_module,
		int32_t num)
{
	int32_t i, ret, ch;
	struct tms_fibersection_val *fiber_val;
	ret = 0;
	ch =  pfiber_cfg->otdr_param.pipe;
	fiber_val = pfiber_cfg->fiber_val;


	for(i = 0; i < num; i++)
	{
		fiber_val_module[i].alarmth1_db = fiber_val[i].level1;
		fiber_val_module[i].alarmth2_db = fiber_val[i].level2;
		fiber_val_module[i].alarmth3_db = fiber_val[i].listen_level;
		fiber_val_module[i].endserialnumberpos = fiber_val[i].end_coor;
		fiber_val_module[i].segmentloss_db = fiber_val[i].fibe_atten_init;
		fiber_val_module[i].segmentnumber = fiber_val[i].fiber_num;
		fiber_val_module[i].startserialnumberpos = fiber_val[i].start_coor;
		fiber_val_module[i].pipenumber = ch;
	}

	return ret;
}
//分配告警模块接口以及管理告警所需的缓冲区
int32_t malloc_alarmmodule_resource(int32_t fiber_sec_num, struct _tagAlarmModuleAdpt *pAlarmAdpt)
{
	int32_t ret, max_sec_num;
	ret = 0;
	if(fiber_sec_num > pAlarmAdpt->max_sec_num){
		free_alarmmodule_resource(pAlarmAdpt);
		pAlarmAdpt->max_sec_num = fiber_sec_num;
	}
	max_sec_num = pAlarmAdpt->max_sec_num;
	//执行到这里，满足条件：缓冲区已经分配，且光纤段数目小于已经分配的光线段数目
	if(pAlarmAdpt->fiber_sec.fibersegment == NULL)
		pAlarmAdpt->fiber_sec.fibersegment= (FiberSegment_t*)malloc(sizeof(FiberSegment_t)*max_sec_num);

	if(pAlarmAdpt->cur_alarm.fiberalarm == NULL)
		pAlarmAdpt->cur_alarm.fiberalarm =  (FiberAlarm_t*)malloc(max_sec_num*sizeof(FiberAlarm_t));

	if(pAlarmAdpt->alarm_cache.palarm == NULL)
		pAlarmAdpt->alarm_cache.palarm = ( struct _tagSecAlarm *)malloc(max_sec_num*sizeof( struct _tagSecAlarm));


	if(pAlarmAdpt->alarm_cache.palarm == NULL || pAlarmAdpt->fiber_sec.fibersegment == NULL
			|| pAlarmAdpt->alarm_cache.palarm == NULL){
		free_alarmmodule_resource(pAlarmAdpt);
		pAlarmAdpt->max_sec_num = 0;
		ret = 1;
		exit_self(ret, __FUNCTION__,__LINE__,"malloc alarm cache error");
	}
	memset(pAlarmAdpt->cur_alarm.fiberalarm, 0, sizeof(FiberAlarm_t)*pAlarmAdpt->max_sec_num);
	memset(pAlarmAdpt->alarm_cache.palarm, 0, sizeof(struct _tagSecAlarm)*pAlarmAdpt->max_sec_num);


	return ret;
}
//分配告警模块接口以及管理告警所需的缓冲区
int32_t free_alarmmodule_resource(struct _tagAlarmModuleAdpt *pAlarmAdpt)
{
	if(pAlarmAdpt->cur_alarm.fiberalarm != NULL){
		free(pAlarmAdpt->cur_alarm.fiberalarm) ;
		pAlarmAdpt->cur_alarm.fiberalarm = NULL;

	}
	if(pAlarmAdpt->alarm_cache.palarm != NULL){
		free(pAlarmAdpt->alarm_cache.palarm);
		pAlarmAdpt->alarm_cache.palarm = NULL;
	}
	intial_alarmmodule_adpt(pAlarmAdpt);
	return 0;
}
//初始化告警模块适配层
int32_t intial_alarmmodule_adpt(struct _tagAlarmModuleAdpt *pAlarmAdpt)
{
	pAlarmAdpt->alarm_cache.sec_num = 0;
	pAlarmAdpt->alarm_cache.palarm = NULL;
	pAlarmAdpt->cur_alarm.alarmnum = 0;
	pAlarmAdpt->cur_alarm.fiberalarm = NULL;
	pAlarmAdpt->fiber_sec.fibersegment = NULL;
	pAlarmAdpt->fiber_sec.fibersegmentnum = 0;
	pAlarmAdpt->is_initial = 0;
	pAlarmAdpt->max_sec_num = 0;
	pAlarmAdpt->sec_num = 0;
	pAlarmAdpt->std_curv.testresult.curvepoint = pAlarmAdpt->data_buf;
	pAlarmAdpt->std_curv.testresult.eventinfo = pAlarmAdpt->event_buf;
	pAlarmAdpt->std_curv.testresult.sectioninfo = pAlarmAdpt->event_sec_buf;
	
	return 0;

}
//事件点从算法转换到模块格式
int32_t convert_event_algor2alarmmodule(
	       	const EventPoint_t ep_algo_buf[],
		OTDRTestResult_t  *tr_alarm,
		int32_t ep_num)
{
	int i;
	OTDREvent_t *ep_alarm_buf;
	ep_alarm_buf = tr_alarm->eventinfo;
	tr_alarm->eventnum = ep_num;

	for(i = 0; i < ep_num; i++)
	{
		ep_alarm_buf[i].echoloss_db = ep_algo_buf[i].EventReturnloss;
		ep_alarm_buf[i].endserialnumberpos = ep_algo_buf[i].EventEnd;
		ep_alarm_buf[i].eventtype = ep_algo_buf[i].EventType;
		ep_alarm_buf[i].insertloss_db = ep_algo_buf[i].EventInsertloss;
		ep_alarm_buf[i].startserialnumberpos = ep_algo_buf[i].EventStart;
		ep_alarm_buf[i].totalloss_db = ep_algo_buf[i].EventTotalloss;
	}
	return 0;
}
//事件列表中的光线段转换算法模块转换到模块格式
int32_t convert_efs_algor2alarmmodule(
		const FiberSection_t efs_algo_buf[],
		OTDRTestResult_t  *tr_alarm,
		int32_t efs_num)
{
	int i;
	FiberSectionByEvent_t *efs_alarm_buf;
	efs_alarm_buf = tr_alarm->sectioninfo;
	tr_alarm->fibersectionnum = efs_num;
	for(i = 0; i < efs_num;i++)
	{
		efs_alarm_buf[i].sectionattencoef_dbkm = efs_algo_buf[i].FiberSectionAttenCoef;
		efs_alarm_buf[i].sectionlen_m = efs_algo_buf[i].FiberSectionLen;
		efs_alarm_buf[i].sectionloss_db = efs_algo_buf[i].FiberSectionLoss;
	}
	return 0;
}
//测量参数从算法模块转换到模块
int32_t convert_para_algor2alarmmodule(
		const OtdrTestParam_t *palgo_para,
		OTDRTestPara_t *palarm_para)
{
	palarm_para->endthreshold_db = palgo_para->EndThreshold;
	palarm_para->gi = palgo_para->n;
	palarm_para->lambda_nm = palgo_para->Lambda_nm;
	palarm_para->measurelength_m = palgo_para->MeasureLength_m;
	palarm_para->nonreflex_db = palgo_para->NonReflex;
	palarm_para->pulsewidth_ns = palgo_para->PulseWidth_ns;
	palarm_para->rsvd1 = palgo_para->rsvd1;
	palarm_para->rsvd2 = palgo_para->rsvd2;
	palarm_para->rsvd3 = 0;
	palarm_para->samplerate_hz = palgo_para->SampleRate_Hz;
	palarm_para->testtime_ms = palgo_para->MeasureTime_ms;
	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  convert_tr_algor2alarmmodule 将曲线中的测量结果从算法转换到模块
 *
 * @param palgor_tr
 * @param palarm_tr
 *
 * @returns   0 成功
 */
/* ----------------------------------------------------------------------------*/
int32_t convert_tr_algor2alarmmodule(
		const OtdrTestResult_t *palgor_tr,
		OTDRTestResult_t *palarm_tr)
{
	
	palarm_tr->fiberlen_m = palgor_tr->FiberLen;
	palarm_tr->fiberloss_db = palgor_tr->FiberLoss;
	palarm_tr->fiberloss_db = palgor_tr->FiberLoss;
	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  compare_alarm 比较两个告警是否相同，位置，级别，类型
 *
 * @param palarm_cache
 * @param palarm_cur
 *
 * @returns  0 相同，1不相同 
 */
/* ----------------------------------------------------------------------------*/
int32_t compare_alarm(
		FiberAlarm_t *palarm_cache, 
		FiberAlarm_t *palarm_cur)
{
	int ret ,error_distance;
	error_distance = palarm_cache->errordistance_m;
	//比较级别，位置，段号
	if(error_distance < palarm_cur->errordistance_m)
		error_distance = palarm_cur->errordistance_m;
	ret = 1;
	if(palarm_cache->alarmlevel != palarm_cur->alarmlevel)
		goto usr_exit;
	if(abs(palarm_cache->alarmpos_m - palarm_cur->alarmpos_m) > error_distance)
		goto usr_exit;
	if(palarm_cache->segmentnumber !=  palarm_cur->segmentnumber)
		goto usr_exit;
	ret = 0;
usr_exit:
	return ret;

}
int32_t compare_alarm_v1(
		FiberAlarm_t *palarm_cache, 
		struct _tagAlarm *palarm_cur)
{
	int ret ,error_distance;
	error_distance = palarm_cache->errordistance_m;
	//比较级别，位置，段号
	ret = 1;
	if(palarm_cache->alarmlevel != palarm_cur->lev)
		goto usr_exit;
	if(abs(palarm_cache->alarmpos_m - palarm_cur->pos[0]) > error_distance)
		goto usr_exit;
	if(palarm_cache->segmentnumber !=  palarm_cur->sec)
		goto usr_exit;
	ret = 0;
usr_exit:
	return ret;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  get_max_serious_alarm 从告警缓冲区中获取最严重的告警
 *
 * @param pCHAlarmCache
 *
 * @returns   告警级别
 */
/* ----------------------------------------------------------------------------*/
int32_t get_max_serious_alarm(FiberAlarmInfo_t *pCurAlarm )
{
	int32_t i, lev, no_alarm;
	no_alarm = 1;
	lev = FIBER_ALARM_LEV3;
	for (i = 0; i < pCurAlarm->alarmnum; i++)
	{
		if(pCurAlarm->fiberalarm[i].alarmlevel > FIBER_ALARM_LEV0)
		{
			no_alarm = 0;
			if(pCurAlarm->fiberalarm[i].alarmlevel < lev)
				lev = pCurAlarm->fiberalarm[i].alarmlevel;
		}
	}
	//没有找到告警，告警级别为0
	if(no_alarm == 1)
		lev = FIBER_ALARM_LEV0;

	return lev;
}

/* --------------------------------------------------------------------------*/
/**
 * @synopsis  initial_alarm_cache 初始化告警cache,cache分配之后第一件要做的事情
 *
 * @param pAlarmCache	告警缓存区指针
 * @param sec_num	段的总数
 *
 * @returns  0成功 
 */
/* ----------------------------------------------------------------------------*/
int32_t initial_alarm_cache(
		struct _tagCHAlarmCache *pAlarmCache,
		int32_t sec_num)
{
	int32_t i;
	pAlarmCache->sec_num = sec_num;
	for(i = 0; i < sec_num;i++)
	{
		memset(&pAlarmCache->palarm[i].alarm, 0, sizeof(FiberAlarm_t));
		pAlarmCache->palarm[i].fade_count = 0;
		pAlarmCache->palarm[i].occur_count = 0;
		
	}
	return 0;
}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  refresh_alarm_cache 每次调用告警模块都要更新告警cache
 *
 * @param pAlarmCache
 * @param pCurAlarm
 * @param pHostAlarm
 *
 * @returns   0 切换到下一个通道测量，1，不切换通道再次测量，2发送总的告警
 */
/* ----------------------------------------------------------------------------*/
int32_t refresh_alarm_cache(
		struct _tagCHAlarmCache *pAlarmCache,
		FiberAlarmInfo_t *pCurAlarm,
		struct _tagSecFiberAlarm *pHostAlarm)
{
	int32_t i, j, refresh_host, ret;
	int32_t re_test,max_test_num;
	//如果告警发生变化，需要上报总的告警
	refresh_host = 0;
	//如果告警次数小于或者告警消失次数小于某值，需要重新测量
	re_test = 0;
	/*
	 *每个通道告警发生变化，告警状态不定，需要连续测量确定告警状态
	 *在超过最大测量次数仍不能确定告警状态，那么跳过当前通道继续测量
	 *最大测量次数为告警产生或者消失确定次数
	*/
	pAlarmCache->test_num++;
	max_test_num = CH_MAX_TEST_NUM;
	//本次没有找到告警
	if(pCurAlarm->alarmnum == 0)
	{

		for(i = 0; i < pAlarmCache->sec_num;i++)
		{
			pAlarmCache->palarm[i].fade_count++;
			//2017-09-14 告警只要消失一次，告警发生次数就变0 
			pAlarmCache->palarm[i].occur_count = 0;
			if(pAlarmCache->palarm[i].fade_count == ALARM_FADE_NUM)
			{
				/*
				 * 2017-09-18 每个测量周期结束，fade_cout 都会清零
				 * 为了重复发送告警，pHostAlarm->buf[i].lev 不能初始化
				 * 为0 即无告警状态
				*/
				if(pHostAlarm->buf[i].lev != FIBER_ALARM_LEV0)
					refresh_host = 1;

				if(pHostAlarm->buf[i].lev > FIBER_ALARM_LEV0)
					pHostAlarm->alarm_num--;
				pHostAlarm->buf[i].lev = FIBER_ALARM_LEV0;
			}
			else if(pAlarmCache->palarm[i].fade_count < ALARM_FADE_NUM)
			{
				re_test = 1;
				//max_test_num = ALARM_FADE_NUM;
			}
		}
	}
	else 
	{
		//定位出告警位置
		for(i = 0; i < pCurAlarm->alarmnum;i++)
		{
			if(pCurAlarm->fiberalarm[i].alarmlevel > FIBER_ALARM_LEV0)
				break;
		}
		ret = compare_alarm(&pAlarmCache->palarm[i].alarm, &pCurAlarm->fiberalarm[i]);
		//2017-09-14 只要发现一次告警，告警消失次数变为0
		pAlarmCache->palarm[i].fade_count = 0;
		//相同
		if(ret == 0)
		{
			pAlarmCache->palarm[i].occur_count++;
			//与正式告警相比较，如果不相同则更新 2017-09-14
			ret = compare_alarm_v1(&pAlarmCache->palarm[i].alarm, &pHostAlarm->buf[i]);
			if(pAlarmCache->palarm[i].occur_count == ALARM_TRIGGER_NUM && ret != 0)
			{
				refresh_host = 1;
				//pAlarmCache->palarm[i].fade_count = 0;
				if(pHostAlarm->buf[i].lev < FIBER_ALARM_LEV1)
					pHostAlarm->alarm_num++;
				//2017-08-14 使用最近一次的告警
				memcpy(&pAlarmCache->palarm[i].alarm, &pCurAlarm->fiberalarm[i], sizeof(FiberAlarm_t));
				convert_alarm_moudule2host(&pAlarmCache->palarm[i].alarm,&pHostAlarm->buf[i],pHostAlarm->ch);
				//i段告警确认，前面的告警全部消失，且不用重新测量
				for(j = 0; j < i; j++)
				{
					if(pAlarmCache->palarm[j].alarm.alarmlevel != FIBER_ALARM_LEV0)
					{
						memset(&pAlarmCache->palarm[j], 0, sizeof(struct _tagSecAlarm));
						pHostAlarm->alarm_num--;
						convert_alarm_moudule2host(&pAlarmCache->palarm[i].alarm,\
							       	&pHostAlarm->buf[i],pHostAlarm->ch);
					}
				}

				printf("verify alarm ch %d sec %d pos %d lev %d diff-d %d diff-l %.3f alarm_count %d\n",\
						pHostAlarm->buf[i].ch,\ 
						pHostAlarm->buf[i].sec, pHostAlarm->buf[i].pos[0],\
						pHostAlarm->buf[i].lev,pHostAlarm->buf[i].error_distance,\
						pHostAlarm->buf[i].loss_diff, pAlarmCache->palarm[i].occur_count);
			}
			else if(pAlarmCache->palarm[i].occur_count < ALARM_TRIGGER_NUM){
				re_test = 1;
				//max_test_num = ALARM_TRIGGER_NUM;
			}
		}
		//如果不相同，直接用最新的覆盖最老的告警
		else 
		{
			pAlarmCache->palarm[i].occur_count = 1;
			memcpy(&pAlarmCache->palarm[i].alarm, &pCurAlarm->fiberalarm[i], sizeof(FiberAlarm_t));
			re_test = 1;
		}
	}
	/*
	 *需要重新测量，且当前测试次数小于最大数目，继续对当前通道进行测量
	 *需要重新测量，当前最大测试次数大于允许次数，对下一通道进行测量
	 *不需要重新测量，那么当前测试次数设置成0
	 *2017-08-29
	 *max_test_num 好像没有什么用,ALARM_TRIGGER_NUM ALARM_FADE_NUM 
	 *可以满足告警产生，告警消失不同次数，另外在定义一个最大测试次数
	 *最大测试次数内满足条件，就切换，否则就继续
	 */
usr_exit:
	if(pAlarmCache->test_num < CH_MIN_TEST_NUM || re_test && pAlarmCache->test_num < max_test_num)
		ret = CONTINUE_TEST;
	else
	{
		if(re_test && pAlarmCache->test_num >= max_test_num)
			ret = SWITCH_CH;
		//新周期开始，就清空告警缓冲区
		memset(pAlarmCache->palarm, 0, sizeof(struct _tagSecAlarm)*pAlarmCache->sec_num);
		printf("%s: %d ch %d total test num %d , this cyc end ! \n", __FUNCTION__, __LINE__,\
				pHostAlarm->ch, pAlarmCache->test_num);
		pAlarmCache->test_num = 0;
	}
	//如果需要更新host告警返回2
	if(refresh_host)
		ret = SEND_ALARM_AND_SWITCH_CH;
	assert(pHostAlarm->alarm_num >= 0 );	
	assert(pHostAlarm->alarm_num <= pHostAlarm->sec_num);	
	return ret;

}
/* --------------------------------------------------------------------------*/
/**
 * @synopsis  convert_alarm_moudule2host 将告警从模块格式转换host格式
 *
 * @param pmodule_alarm
 * @param ch
 *
 * @returns   0 成功
 */
/* ----------------------------------------------------------------------------*/
int32_t convert_alarm_moudule2host( 
		FiberAlarm_t *pmodule_alarm, 
		struct _tagAlarm *phost_alarm,
		int32_t ch)
{
	phost_alarm->lev = pmodule_alarm->alarmlevel;
	phost_alarm->ch = ch;
	phost_alarm->pos[0] = pmodule_alarm->alarmpos_m;
	phost_alarm->sec = pmodule_alarm->segmentnumber;
	phost_alarm->type = pmodule_alarm->alarmtype;
	phost_alarm->loss_diff = pmodule_alarm->alarmlosschangevalue_db;
	phost_alarm->error_distance = pmodule_alarm->errordistance_m;
	return 0;

}

int32_t refresh_fiber_statistc(
		const OtdrTestResult_t *tr,
		struct _tagCHFiberSec *pfiber_sec,
		int32_t ch)
{
	int32_t i, start, end;
	int32_t ret;
	struct _tagFiberSecCfg *ppara;		//光线段配置参数
	struct _tagFiberStatisData *pstatis;	//统计数据
	ret = 0;
	ppara = &pfiber_sec->para;
	pstatis = &pfiber_sec->statis;
	pstatis->ch = ch;
	pstatis->sec_num = ppara->fiber_hdr.count;
	pstatis->counts++;
	pstatis->state = 0;
	for(i = 0; i < ppara->fiber_hdr.count; i++)
	{
		start = ppara->fiber_val[i].start_coor;
		end = ppara->fiber_val[i].end_coor;
		pstatis->buf[i].sec = ppara->fiber_val[i].fiber_num;
		pstatis->buf[i].attu = fabs(tr->Ai[start] - tr->Ai[end]);
	}
	return ret;
}
#ifdef __cplusplus
extern  "C"{
#endif
